FlameWarden = {};
local flameZones;
local function setZone(z, f, h)
	flameZones[z], flameZones["*" .. z] = f, h;
end
local function popZones(z, ...)
	if not z then return; end
	setZone(z, true, true);
	return popZones(...);
end
local function populateZones()
	flameZones = {};
	local ofs = UnitFactionGroup("player") == "Alliance" and 0 or 3;
	for i=1022+ofs,1024+ofs do for j=1,GetAchievementNumCriteria(i) do
		flameZones[GetAchievementCriteriaInfo(i,j)] = true;
	end end
	for i=1028+ofs,1030+ofs do for j=1,GetAchievementNumCriteria(i) do
		flameZones["*" .. GetAchievementCriteriaInfo(i,j)] = true;
	end	end
	SetMapZoom(4);
	popZones(GetMapZones(4));
	setZone((UpdateMapHighlight(0.40, 0.30))); -- Icecrown
	setZone((UpdateMapHighlight(0.35, 0.50))); -- WG
	for i=1, GetNumMapLandmarks() do
		local n = GetMapLandmarkInfo(i);
		if n then setZone(n); end -- One of those is Dalaran.
	end
end
function FlameWarden.IsZoneDesecrated(zone)
	return FlameWardenLog and FlameWardenLog["*" .. zone];
end
function FlameWarden.IsZoneHonoured(zone)
	return FlameWardenLog and FlameWardenLog[zone];
end
function FlameWarden.DesecrateZone(zone)
	FlameWardenLog = FlameWardenLog or {};
	FlameWardenLog["*" .. zone] = select(4, CalendarGetDate());
	FlameWarden.Update(zone, false);
end
function FlameWarden.HonourZone(zone)
	FlameWardenLog = FlameWardenLog or {};
	FlameWardenLog[zone] = select(4, CalendarGetDate())
	FlameWarden.Update(zone, true);
end
function FlameWarden.GetZoneState(zone)
	zone = zone or GetRealZoneText();
	if not flameZones then populateZones(); end
	return FlameWarden.IsZoneHonoured(zone) or (flameZones[zone] and 0), FlameWarden.IsZoneDesecrated(zone) or (flameZones["*" .. zone] and 0);
end
function FlameWarden.Update(zone, isFriendly)
	-- Override me. Or not. See if I care.
end

local events = CreateFrame("Frame", "FlameWardenEventTracker");
local getQuestReward; do
	local pat = "^" .. ERR_QUEST_REWARD_ITEM_MULT_IS:gsub("%.", "%%."):gsub("%%0?1?$?d", "(%%d+)"):gsub("%%0?2?$?s", "(.-)") .. "$";
	function getQuestReward(message)
		local quant, link = message:match(pat);
		if not quant then return; end
		if quant:match("%D") and not link:match("|Hitem:") then
			quant, link = link, quant;
		end
		return tonumber(quant), tonumber(link:match("|Hitem:(%d+)"));
	end
end
local function validateQuest(guid, title, qtype)
	local typeDigit = tonumber(guid:match("^0x%x%x(%x)"), 16) % 8;
	return (typeDigit == 3 and qtype == "honor") or (typeDigit ~= 3 and qtype == "desecrate");
end

local npcGUID, questTitle, matchingGossip;
function events:CHAT_MSG_SYSTEM(message)
	if not matchingGossip then return; end
	local quant, id = getQuestReward(message);
	if quant == 5 and id == 23247 and validateQuest(npcGUID, questTitle, "honor") then
		FlameWarden.HonourZone(GetZoneText());
		matchingGossip = false;
	elseif quant == 10 and id == 23247 and validateQuest(npcGUID, questTitle, ("desecrate")) then
		FlameWarden.DesecrateZone(GetZoneText());
		matchingGossip = false;
	end
end
function events:QUEST_COMPLETE()
	npcGUID, questTitle = UnitGUID("questnpc"), GetTitleText();
end
function events:GOSSIP_SHOW()
	local title, level, flag = GetGossipAvailableQuests();
	matchingGossip = (level == -1 and flag == nil) and select("#", GetGossipAvailableQuests()) == 3 and select("#", GetGossipActiveQuests()) == 0;
end
for k,v in pairs(events) do
	if type(v) == "function" then
		events:RegisterEvent(k);
	end
end

events:SetScript("OnEvent", function(s,e,...) s[e](s, ...); end);